package com.efrei.schoolmanager.controlers;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.efrei.schoolmanager.exceptions.LogicException;
import com.efrei.schoolmanager.model.hibernate.HibernateUtil;

/**
 * s'occupe de la logique transactionnelle des controleurs.
 * <ul>
 * <li>{@link ControleurTransactionnel#validAndQuit() validAndQuit} permet de
 * valider et fermer proprement les ressources</li>
 * <li>{@link ControleurTransactionnel#toutAnnuler() toutAnnuler} ou non
 * validation des actions entraine une annulation de ces derniers</li>
 * </ul>
 * 
 * @see ControleurTransactionnel#validAndQuit()
 * @see ControleurTransactionnel#toutAnnuler()
 */
public abstract class ControleurTransactionnel {
	// session et transaction de l'écran
	private Session session = null;
	private Transaction tx = null;

	public ControleurTransactionnel() throws HibernateException, LogicException {
		// ouverture de la transaction
		session = HibernateUtil.getSession();
		// on verifie que l'ancienne transaction a bien été fermé
		try {
			session.getTransaction().rollback();
			System.out
					.println("ancienne transaction toujours ouverte, rollback et reopen");
		} catch (HibernateException e) {
			// la transaction n'était pas la
			System.err
					.println("L'ancienne session avait été correctement fermée ("
							+ e + ")");
			try {
				session.close();
			} catch (Exception ex) {
				System.err.println("Session était déjà fermée (" + ex + ")");
			} finally {
				System.err
						.println("Si pas d'exception, session.close() a réussi");
			}
		}
		session = HibernateUtil.getSession();
		tx = session.beginTransaction();
	}

	/**
	 * a appeler à la fermeture de l'écran pour valider les actions effectués
	 * sur l'écran
	 */
	public void validAndQuit() throws LogicException {
		if (tx != null)
			tx.commit();
		nettoyerFermetureSession();
	}

	/**
	 * pour annuler toutes les actions effectués en base pour l'écran courant
	 */
	public void toutAnnuler() {
		close();
	}

	/**
	 * a appeler pour fermer les ressources courantes et nettoyer les ressources
	 */
	public void close() {
		if (tx != null)
			tx.rollback();
		nettoyerFermetureSession();
	}

	/**
	 * pour tout mettre à null et donc ne pas réutiliser des objets fermés
	 */
	private void nettoyerFermetureSession() {
		session = null;
		tx = null;
	}

	public Session getSession() {
		return session;
	}
}
